package com.nexgo.payment.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.nexgo.common.ByteUtils;
import com.nexgo.common.TlvUtils;
import com.nexgo.jbigkit.JbigKit;
import com.nexgo.oaf.apiv3.DeviceInfo;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.printer.AlignEnum;
import com.nexgo.oaf.apiv3.device.printer.BarcodeFormatEnum;
import com.nexgo.oaf.apiv3.device.printer.DotMatrixFontEnum;
import com.nexgo.oaf.apiv3.device.printer.FontEntity;
import com.nexgo.oaf.apiv3.device.printer.OnPrintListener;
import com.nexgo.oaf.apiv3.device.printer.Printer;
import com.nexgo.payment.App;
import com.nexgo.payment.BuildConfig;
import com.nexgo.payment.R;
import com.nexgo.payment.api.ApiDeviceEngine;
import com.nexgo.payment.constrant.OfflineState;
import com.nexgo.payment.constrant.PreferencesConstants;
import com.nexgo.payment.constrant.SysConstant;
import com.nexgo.payment.constrant.TransType;
import com.nexgo.payment.databases.Classification;
import com.nexgo.payment.databases.Repository;
import com.nexgo.payment.databases.SettleInfo;
import com.nexgo.payment.databases.Signature;
import com.nexgo.payment.databases.Statistics;
import com.nexgo.payment.databases.TransRecord;

import java8.util.Optional;

import static com.nexgo.payment.constrant.TransType.AUTH;

/**
 * 打印操作类
 * Created by xiaox on 2017/3/9.
 */
public class PrintHelper {

    private static final FontEntity FONT_SMALL = new FontEntity(DotMatrixFontEnum.CH_SONG_20X20, DotMatrixFontEnum.ASC_SONG_8X16);
    private static final FontEntity FONT_NORMAL = new FontEntity(DotMatrixFontEnum.CH_SONG_24X24, DotMatrixFontEnum.ASC_SONG_12X24);
    private static final FontEntity FONT_BOLD = new FontEntity(DotMatrixFontEnum.CH_SONG_32X32, DotMatrixFontEnum.ASC_SONG_16X32);
    private static final FontEntity FONT_BIG = new FontEntity(DotMatrixFontEnum.CH_SONG_24X24, DotMatrixFontEnum.ASC_SONG_12X24, false, true);
    private static final Printer mPrinter = ApiDeviceEngine.getInstance().getPrinter();
    private static final Repository mRepository = Repository.getInstance();

    /**
     * 初始化打印机相关参数
     */
    public static int printerCfgInit() {
        int result = mPrinter.initPrinter();
        if (result == SdkResult.Success) {
            //mPrinter.setLetterSpacing(4);
            //mPrinter.setGray(GrayLevelEnum.LEVEL_2);
        }
        return result;
    }

    /**
     * 判断是否缺纸
     *
     * @return true:是，false:否
     */
    public static boolean isPaperLack() {
        return mPrinter.getStatus() == SdkResult.Printer_PaperLack;
    }

    /**
     * 组织签购单打印数据
     *
     * @param transRecord 交易信息
     * @param printTimes  打印次数
     * @param totalTimes
     * @param isRePrint   是否重打印
     */
    public static void formPrintTransData(TransRecord transRecord, int printTimes, int totalTimes, boolean isRePrint) {
        System.out.println("------------组织签购单打印数据---------");
        TransType transType = TransType.values()[transRecord.getTransType()];
        boolean scanTrans = TransUtils.isScanTrans(transType);
        formPrintTitle();
        keeper(printTimes, totalTimes);
        mPrinter.appendPrnStr("商户名称(MERCHANT NAME):", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr(mRepository.getParamValue(PreferencesConstants.MERCHANT_NAME), FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("商户编号(MERCHANT NO.):", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr(transRecord.getMerchantId(), FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("终端编号(TERMINAL NO.):", transRecord.getTerminalId(), FONT_NORMAL);
        mPrinter.appendPrnStr("操作员号(OPERATOR NO.):", String.format(SysConstant.LOCALE, "%02d", transRecord.getOperator()), FONT_NORMAL);
        mPrinter.appendPrnStr("收单行号(ACQUIRING NO.):", mRepository.getParamValue(PreferencesConstants.ACQUIRING_NUMBER), FONT_NORMAL);
        if (!scanTrans) {
            mPrinter.appendPrnStr(scanTrans ? "支付码号(PAY CODE NO.):" : "卡号(CARD NO.):", FONT_NORMAL, AlignEnum.LEFT);

            if (transType == AUTH) {
                mPrinter.appendPrnStr(transRecord.getPan(), FONT_BOLD, AlignEnum.LEFT);
            } else {
                mPrinter.appendPrnStr(TransUtils.maskPan(scanTrans ? transRecord.getPayCodeNo() : transRecord.getPan()), FONT_BOLD, AlignEnum.LEFT);
            }

            //        wzp add
            mPrinter.appendPrnStr("卡序列号(CARD SN):", transRecord.getCsn(), FONT_NORMAL);
            mPrinter.appendPrnStr("卡类别(CARD TYPE):", transRecord.getCardType(), FONT_NORMAL);
            mPrinter.appendPrnStr("有效期(EXP DATE):", Optional.ofNullable(transRecord.getExpDate())
                    .filter(s -> s.length() == 4)
                    .map(s -> new StringBuilder(s).insert(0,"20").insert(4, '/').toString())
                    .orElse(""), FONT_NORMAL);
        }
        mPrinter.appendPrnStr("日期/时间(DATE/TIME):", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr(StringUtils.formatDateTime(transRecord.getDate(), transRecord.getTime()), FONT_NORMAL, AlignEnum.LEFT);
        if (!scanTrans) {
            if (TransType.EC_SALE.equals(transType)){
                String str =   Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f74"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase();
                Log.d("9f74", "formPrintTransData: " + str);

                mPrinter.appendPrnStr("授权码(AUTH NO.):" ,ByteUtils.asciiByteArray2String(ByteUtils.commonString2Bcd(str)), FONT_NORMAL);
            }else{
                mPrinter.appendPrnStr("授权码(AUTH NO.):", transRecord.getAuthCode(), (AUTH.equals(transType)) ? FONT_BOLD : FONT_NORMAL);
            }

        }
        mPrinter.appendPrnStr("批次号(BATCH NO.):", transRecord.getBatchNum(), FONT_NORMAL);
        mPrinter.appendPrnStr("凭证号(VOUCHER NO.):", transRecord.getTraceNum(), FONT_NORMAL);
       if(!scanTrans) {
           mPrinter.appendPrnStr("参考号(REFER NO.):", transRecord.getRefNum(), FONT_NORMAL);
       }
        mPrinter.appendPrnStr("交易类型(TRANS TYPE):", FONT_NORMAL, AlignEnum.LEFT);

        mPrinter.appendPrnStr(App.sContext.getString(transType.getName())
                + " /"
                + App.sContext.getString(transType.getEnName())
                + TransUtils.getCardEntryModeSymbol(transRecord.getEntryMode()), FONT_BIG, AlignEnum.LEFT);
        if(scanTrans){
            if(transRecord.getScanChannel() != null) {
                if (transRecord.getScanChannel().equals("01")) {
                    mPrinter.appendPrnStr("支付渠道:" + "微信", FONT_NORMAL, AlignEnum.LEFT);
                } else if (transRecord.getScanChannel().equals("02")) {
                    mPrinter.appendPrnStr("支付渠道:" + "支付宝", FONT_NORMAL, AlignEnum.LEFT);
                } else if (transRecord.getScanChannel().equals("03")) {
                    mPrinter.appendPrnStr("支付渠道:" + "银联二维码", FONT_NORMAL, AlignEnum.LEFT);
                }
            }
        }
        if (scanTrans) {
            //根据付款凭证码生成条形码
            mPrinter.appendPrnStr("订单号(ORDER NO):", FONT_NORMAL, AlignEnum.LEFT);
            //
            if (!TextUtils.isEmpty(transRecord.getPayTraceCode())) {
                mPrinter.appendBarcode(transRecord.getPayTraceCode(), 100, 0, 1, BarcodeFormatEnum.CODE_128, AlignEnum.CENTER);
                mPrinter.appendPrnStr("  ", FONT_NORMAL, AlignEnum.LEFT);
                mPrinter.appendQRcode(transRecord.getPayTraceCode(), 190, AlignEnum.CENTER);
            }
        }

        mPrinter.appendPrnStr("交易金额(AMOUNT):", FONT_NORMAL, AlignEnum.LEFT);
        String minus = "";
        if ("1".equals(mRepository.getParamValue(PreferencesConstants.VOID_CLASS_NEED_PRINT_MINUS_SIGN))) {
            if (TransUtils.isVoidTrans(transType) || TransUtils.isRefundTrans(transType))
                minus += "-";
        }
        mPrinter.appendPrnStr("    RMB " + minus + StringUtils.formatAmount(transRecord.getAmount(), SysConstant.FUND_DIGITS), FONT_BOLD, AlignEnum.LEFT);
        if (TransType.EC_SALE.equals(transType)) {
            Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f79"))
                    .map(strings -> {
                        if (strings.size() == 0) {
                            return TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f5a");
                        } else {
                            return strings;
                        }
                    })
                    .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                    .filter(s -> !TextUtils.isEmpty(s))
                    .map(s -> StringUtils.formatAmount(s, SysConstant.FUND_DIGITS))
                    .ifPresent(s -> mPrinter.appendPrnStr("电子现金余额:RMB " + s, FONT_NORMAL, AlignEnum.LEFT));
        }


        /*else
           if (transRecord.getIsInternational()) {
            mPrinter.appendPrnStr("外卡组织:" + transRecord.getInterOrgCode(), FONT_NORMAL, AlignEnum.LEFT);
        }*/

        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        if(TransType.AUTH.equals(transType)){
            //预授权+原交易日期+卡有效期+卡号
            StringBuffer sb=new StringBuffer();
            sb.append(transRecord.getAuthCode());
            sb.append(transRecord.getOrgDate());
            if(!TextUtils.isEmpty(transRecord.getExpDate())){
                sb.append(transRecord.getExpDate());
            }
            sb.append(transRecord.getPan());
            String qRcode=sb.toString();
            mPrinter.appendQRcode(qRcode,190, AlignEnum.CENTER);
        }
        mPrinter.appendPrnStr("备注(REFERENCE):", FONT_NORMAL, AlignEnum.LEFT);
        // lr add
        if(transType.equals(TransType.ONLINE_REFUND) && transRecord.getRespCode().equalsIgnoreCase("T1")){
            mPrinter.appendPrnStr("申请已收到，将尽快处理", FONT_NORMAL, AlignEnum.LEFT);
        }
//        formMarketInfo(transRecord);
        formOrgInfo(transRecord);
        if (isRePrint) {
            mPrinter.appendPrnStr("重打印凭证/DUPLICATED", FONT_NORMAL, AlignEnum.LEFT);
        }
//        formField63Info(transRecord);
        formEmvInfo(transRecord);
        formSignatureInfo(transRecord, printTimes);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);

        mPrinter.appendPrnStr("本人确认以上交易,同意将其记入本卡账户", FONT_SMALL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("I ACKNOWLEDGE SATISFACTORY RECEIPT OF RELATIVE GOODS/SERVICES", FONT_SMALL, AlignEnum.LEFT);
        DeviceInfo deviceInfo = ApiDeviceEngine.getInstance().getDeviceInfo();
        //版本打印
        String versionInfo = deviceInfo.getVendor().toUpperCase() + "-" + deviceInfo.getModel() + "-" + BuildConfig.APP_INNER_VERSION;
        mPrinter.appendPrnStr(versionInfo, FONT_SMALL, AlignEnum.LEFT);
//        mPrinter.appendPrnStr("服务热线(HOT LINE):" + Optional.ofNullable(mRepository.getParamValue(PreferencesConstants.SERVICE_PHONE)).orElse(""), versionInfo.toUpperCase(), FONT_SMALL);
    }

    /**
     * 组织营销活动打印信息
     *
     * @param transRecord
     */
    private static void formMarketInfo(TransRecord transRecord) {
        String marketInfo = transRecord.getMarketInfo();
        if (TextUtils.isEmpty(marketInfo)) return;
        //折扣活动名额剩余
        Optional.ofNullable(TlvUtils.decodingTLV(marketInfo, "33"))
                .filter(strings -> strings.size() != 0)
                .map(strings -> strings.get(0))
                .filter(s -> !TextUtils.isEmpty(s))
                .map(s -> Integer.parseInt(s))
                .ifPresent(integer -> mPrinter.appendPrnStr(integer > 0 ? String.format(SysConstant.LOCALE, "折扣活动名额剩余:%d%%", integer) : "折扣活动结束,请关注银联钱包", FONT_NORMAL, AlignEnum.LEFT));
        //折扣活动ID
        Optional.of(TlvUtils.decodingTLV(marketInfo, "35"))
                .filter(strings -> strings.size() != 0)
                .map(strings -> strings.get(0))
                .map(s -> ByteUtils.hexString2ByteArray(s))
                .map(bytes -> new String(bytes))
                .map(s -> s.trim().toLowerCase())
                .ifPresent(s -> mPrinter.appendPrnStr("折扣活动ID:" + s, FONT_NORMAL, AlignEnum.LEFT));
        //卡片信息 00-贷记卡；01-借记卡；10-准贷记卡
        Optional.ofNullable(TlvUtils.decodingTLV(marketInfo, "36"))
                .filter(strings -> strings.size() != 0)
                .map(strings -> strings.get(0))
                .filter(s -> !TextUtils.isEmpty(s))
                .map(s -> ByteUtils.hexString2ByteArray(s))
                .map(bytes -> bytes[0])
                .map(b -> (b & 0xC0) >> 6)
                .ifPresent(b -> {
                    String card;
                    switch (b) {
                        case 0:
                            card = "贷记卡";
                            break;
                        case 1:
                            card = "借记卡";
                            break;
                        case 2:
                            card = "准贷记卡";
                            break;
                        default:
                            card = "未知";
                            break;
                    }
                    mPrinter.appendPrnStr(card, FONT_NORMAL, AlignEnum.LEFT);
                });

    }

    /**
     * 组织签名打印信息
     *
     * @param transRecord
     * @param printTimes
     */
    private static void formSignatureInfo(TransRecord transRecord, int printTimes) {
        TransType transType = TransType.values()[transRecord.getTransType()];
        boolean scanTrans = TransUtils.isScanTrans(transType);
        Optional.ofNullable(transRecord.getCardHolder())
                .filter(s -> !TextUtils.isEmpty(s))
                .ifPresent(s -> mPrinter.appendPrnStr("持卡人:" + s, FONT_NORMAL, AlignEnum.LEFT));
        boolean isNeedSignature = true;
        if (TransUtils.isQPSSupportTrans(transType)) {
            double freePwdLimit = Double.parseDouble(StringUtils.formatAmount(transRecord.getQpsFreePinAmountLimit(), SysConstant.FUND_DIGITS));
            double freeSignLimit = Double.parseDouble(StringUtils.formatAmount(transRecord.getQpsFreeSignatureAmountLimit(), SysConstant.FUND_DIGITS));
            double printLimit = 0.00f;
            if (transRecord.getIsCdcvm()) {
                isNeedSignature = false;
                mPrinter.appendPrnStr("移动设备已验证用户,免密免签", FONT_NORMAL, AlignEnum.LEFT);
            } else if (transRecord.getIsQpsFreePin() && transRecord.getIsQpsFreeSignature()) {
                isNeedSignature = false;
                if (freePwdLimit <= freeSignLimit) {
                    printLimit = freePwdLimit;
                } else {
                    printLimit = freeSignLimit;
                }
                mPrinter.appendPrnStr(String.format(SysConstant.LOCALE, "交易金额未超%.2f元,免密免签", printLimit), FONT_NORMAL, AlignEnum.LEFT);
            } else if (transRecord.getIsQpsFreePin()) {
                printLimit = freePwdLimit;
                mPrinter.appendPrnStr(String.format(SysConstant.LOCALE, "交易金额未超%.2f元,无需输密", printLimit), FONT_NORMAL, AlignEnum.LEFT);
            } else if (transRecord.getIsQpsFreeSignature()) {
                isNeedSignature = false;
                printLimit = freeSignLimit;
                mPrinter.appendPrnStr(String.format(SysConstant.LOCALE, "交易金额未超%.2f元,免签名", printLimit), FONT_NORMAL, AlignEnum.LEFT);
            }
        } else if (TransType.EC_SALE.equals(transType)
                && "1".equals(mRepository.getParamValue(PreferencesConstants.EC_FREE_SIGNATURE))) {
            isNeedSignature = false;
            mPrinter.appendPrnStr("电子现金免签名", FONT_NORMAL, AlignEnum.LEFT);
        }
        /*else if (scanTrans) {
            isNeedSignature = false;
            mPrinter.appendPrnStr("扫码交易免签名", FONT_NORMAL, AlignEnum.LEFT);
        }*/
        if (isNeedSignature) {
            //打印第一联
            if (printTimes == 0) {
                mPrinter.appendPrnStr("持卡人签名(HOLDER SIGNATURE):", FONT_NORMAL, AlignEnum.LEFT);
                //获取该流水号对应的签名数据
                Signature signature = Repository.getInstance().getSignature(transRecord.getTraceNum());
                //判断电子签名是否存在
                Optional.ofNullable(signature)
                        .map(entity -> entity.getSignatureData())
                        .map(s -> new JbigKit(App.sContext).decompress(Base64.decode(s, Base64.DEFAULT)))
                        .ifPresentOrElse(bitmap -> mPrinter.appendImage(bitmap, AlignEnum.CENTER),
                                () -> mPrinter.appendPrnStr("\n\n", FONT_NORMAL, AlignEnum.LEFT));
            }
        }
    }

    /**
     * 组织 EMV 打印信息
     *
     * @param transRecord
     */
    private static void formEmvInfo(TransRecord transRecord) {
        TransType transType = TransType.values()[transRecord.getTransType()];
        if (!TextUtils.isEmpty(transRecord.getResultTlv())
                //简化流程不打印
                && !TextUtils.isEmpty(transRecord.getEmvTlv())
                //撤销不打印
                && !TransUtils.isVoidTrans(transType)
                //退货不打印
                && !TransUtils.isRefundTrans(transType)
                //通知类不打印
                && !TransUtils.isNotifyTrans(transType)) {
            String value;
            if (!OfflineState.APPROVE.equals(OfflineState.values()[transRecord.getOfflineState()])) {
                mPrinter.appendPrnStr("TC:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f26"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                value = Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "84"))
                        .map(strings -> {
                            if (strings.size() == 0) {
                                return TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f06");
                            } else {
                                return strings;
                            }
                        })
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase();
                mPrinter.appendPrnStr("AID:" + value, FONT_SMALL, AlignEnum.LEFT);
                Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f63"))
                        .filter(strings -> strings.size() != 0)
                        .ifPresent(strings -> mPrinter.appendPrnStr("CPI:" + strings.get(0).toUpperCase(), FONT_SMALL, AlignEnum.LEFT));
            } else {
                mPrinter.appendPrnStr("ARQC:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f26"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                mPrinter.appendPrnStr("TVR:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "95"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase()
                        + " CSN:" + Optional.ofNullable(transRecord.getCsn()).orElse("000").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                value = Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "84"))
                        .map(strings -> {
                            if (strings.size() == 0) {
                                return TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f06");
                            } else {
                                return strings;
                            }
                        })
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase();
                mPrinter.appendPrnStr("AID:" + value, FONT_SMALL, AlignEnum.LEFT);
                mPrinter.appendPrnStr("TSI:"
                        + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9B"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase()
                        + " ATC:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f36"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                mPrinter.appendPrnStr("APPLAB:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "50"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .map(s -> new String(ByteUtils.hexString2ByteArray(s)))
                        .orElse("").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f12"))
                        .filter(strings -> strings.size() != 0)
                        .map(strings -> strings.get(0).toUpperCase())
                        .map(s -> new String(ByteUtils.hexString2ByteArray(s)))
                        .ifPresent(s -> mPrinter.appendPrnStr("APPName:" + s, FONT_SMALL, AlignEnum.LEFT));
                mPrinter.appendPrnStr("UNPR_NUM:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f37"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                value = "AIP:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "82"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase();
                if (!(TransType.SALE.equals(transType) && transRecord.getEntryMode().startsWith("07"))) {
                    value += " CVMR:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f34"))
                            .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                            .orElse("").toUpperCase();
                }
                mPrinter.appendPrnStr(value, FONT_SMALL, AlignEnum.LEFT);
                mPrinter.appendPrnStr("IAD:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f10"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                mPrinter.appendPrnStr("TermCap:" + Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f33"))
                        .map(strings -> strings.size() == 0 ? "" : strings.get(0))
                        .orElse("").toUpperCase(), FONT_SMALL, AlignEnum.LEFT);
                Optional.ofNullable(TlvUtils.decodingTLV(transRecord.getResultTlv(), "9f63"))
                        .filter(strings -> strings.size() != 0)
                        .ifPresent(strings -> mPrinter.appendPrnStr("CPI:" + strings.get(0).toUpperCase(), FONT_SMALL, AlignEnum.LEFT));
            }
        }
    }

    /**
     * 组织63域自定义域返回的信息
     *
     * @param transRecord
     */
    private static void formField63Info(TransRecord transRecord) {
        Optional.ofNullable(transRecord.getIssInfo())
                .ifPresent(s -> mPrinter.appendPrnStr(s, FONT_NORMAL, AlignEnum.LEFT));
        Optional.ofNullable(transRecord.getCupInfo())
                .ifPresent(s -> mPrinter.appendPrnStr(s, FONT_NORMAL, AlignEnum.LEFT));
        Optional.ofNullable(transRecord.getMerAcqInfo())
                .ifPresent(s -> mPrinter.appendPrnStr(s, FONT_NORMAL, AlignEnum.LEFT));
        Optional.ofNullable(transRecord.getPosTerInfo())
                .ifPresent(s -> mPrinter.appendPrnStr(s, FONT_NORMAL, AlignEnum.LEFT));
    }

    /**
     * 组织原始交易打印信息
     *
     * @param transRecord
     */
    private static void formOrgInfo(TransRecord transRecord) {
        System.out.println("----------------333333333333----------------");
        TransType transType = TransType.values()[transRecord.getTransType()];
        if (TransType.AUTH_CM.equals(transType) || TransType.AUTH_VOID.equals(transType)) {
            mPrinter.appendPrnStr("原授权码/AUTH NO.:" + Optional.ofNullable(transRecord.getOrgAuthCode()).orElse(""), FONT_NORMAL, AlignEnum.LEFT);
        } else if (TransUtils.isVoidTrans(transType)) {
            if (TransUtils.isAuthTrans(transType)) {
                mPrinter.appendPrnStr("预授权码/AUTH NO.:" + Optional.ofNullable(transRecord.getOrgAuthCode()).orElse(""), FONT_NORMAL, AlignEnum.LEFT);
                //预授权+原交易日期+卡有效期+卡号
                String qRcode = transRecord.getAcceptCode()+transRecord.getOrgDate()+transRecord.getExpDate()+transRecord.getPan();
                System.out.println("--------AcceptCode:"+transRecord.getAcceptCode()+"--OrgDate:"+transRecord.getOrgDate()+"---ExpDate:"+transRecord.getExpDate()+"---Pan:"+transRecord.getPan());
                mPrinter.appendQRcode(qRcode,190, AlignEnum.CENTER);
            } else {
                mPrinter.appendPrnStr("原凭证号/VOUCHER:" + Optional.ofNullable(transRecord.getOrgTraceNum()).orElse(""), FONT_NORMAL, AlignEnum.LEFT);
            }
        } else if (TransUtils.isRefundTrans(transType)) {
            mPrinter.appendPrnStr("原交易日期/DATE:" + Optional.ofNullable(transRecord.getOrgDate())
                    .map(s -> new StringBuilder(s).insert(2, "/").toString()).orElse(""), FONT_NORMAL, AlignEnum.LEFT);
        }
    }

    public static void formTransDetailHeader() {
        mPrinter.appendPrnStr("交 易 明 细 单", FONT_BIG, AlignEnum.CENTER);
        keeper(0, 1);
        mPrinter.appendPrnStr("凭证号 类型     卡号  ", "金额   授权码 ", FONT_SMALL);
        mPrinter.appendPrnStr("VOUCHER  TYPE     CARD NO", "AMOUNT  AUTH CODE", FONT_SMALL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
    }

    public static void formUploadRejectedTransDetailHeader() {
        mPrinter.appendPrnStr("上送被拒离线明细单", FONT_BIG, AlignEnum.CENTER);
        keeper(0, 1);
        mPrinter.appendPrnStr("凭证号 类型 卡号", "金额  授权码", FONT_SMALL);
        mPrinter.appendPrnStr("VOUCHER TYPE CARD NO", "AMOUNT AUTH CODE", FONT_SMALL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
    }

    public static void formUploadFailTransDetailHeader() {
        mPrinter.appendPrnStr("未成功上送交易明细单", FONT_BIG, AlignEnum.CENTER);
        keeper(0, 1);
        mPrinter.appendPrnStr("凭证号 类型 卡号", "金额  授权码", FONT_SMALL);
        mPrinter.appendPrnStr("VOUCHER TYPE CARD NO", "AMOUNT AUTH CODE", FONT_SMALL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
    }

    /**
     * 组织交易明细打印数据
     *
     * @param transRecord 交易记录
     */
    public static void formPrintTransDetail(TransRecord transRecord) {
        String leftStr;
        String rightStr;
        TransType transType = TransType.values()[transRecord.getTransType()];
        boolean scanTrans = TransUtils.isScanTrans(transType);

        if(scanTrans){
            leftStr = transRecord.getTraceNum() + "  " + StringUtils.leftPad(TransUtils.getTransTypeSymbol(transType), 1, ' ') + "  "
                    + TransUtils.maskPan(transRecord.getPayTraceCode());
            rightStr = StringUtils.formatAmount(transRecord.getAmount(), SysConstant.FUND_DIGITS)
                    + "    " + Optional.ofNullable(transRecord.getScanChannel()).orElse(StringUtils.leftPad("", 2, ' '));
        }else {
            leftStr = transRecord.getTraceNum() + "  " + StringUtils.leftPad(TransUtils.getTransTypeSymbol(transType), 1, ' ') + "  "
                    + TransUtils.maskPan(transRecord.getPan());
            rightStr = StringUtils.formatAmount(transRecord.getAmount(), SysConstant.FUND_DIGITS)
                    + "    " + Optional.ofNullable(transRecord.getAuthCode()).orElse(StringUtils.leftPad("", 6, ' '));
        }
        mPrinter.appendPrnStr(leftStr, rightStr, FONT_SMALL);
    }

    /**
     * 组织交易汇总打印数据
     *
     * @param settleInfo 汇总信息
     */
    public static void formPrintTransSummary(SettleInfo settleInfo) {
        mPrinter.appendPrnStr("交易总计单", FONT_BIG, AlignEnum.CENTER);
        keeper(0, 1);
        mPrinter.appendPrnStr("商户名称:", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr(settleInfo.getMerchantName(), FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("商户编号:", settleInfo.getMerchantId(), FONT_NORMAL);
        mPrinter.appendPrnStr("终端编号:", settleInfo.getTerminalId(), FONT_NORMAL);
        mPrinter.appendPrnStr("操作员号:", String.format(SysConstant.LOCALE, "%02d", settleInfo.getOperator()), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("类型/TYPE   笔数/SUM", "金额/AMT", FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("内卡", FONT_NORMAL, AlignEnum.LEFT);
        Statistics statistics = settleInfo.getStatistics();
        mPrinter.appendPrnStr("借记          " + statistics.getDebitNum(),
                StringUtils.formatAmount(String.valueOf(statistics.getDebitAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("贷记          " + statistics.getCreditNum(),
                StringUtils.formatAmount(String.valueOf(statistics.getCreditAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("外卡", FONT_NORMAL, AlignEnum.LEFT);
        Statistics internationalStatistics = settleInfo.getInterStatistics();
        mPrinter.appendPrnStr("借记          " + internationalStatistics.getDebitNum(),
                StringUtils.formatAmount(String.valueOf(internationalStatistics.getDebitAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("贷记          " + internationalStatistics.getCreditNum(),
                StringUtils.formatAmount(String.valueOf(internationalStatistics.getCreditAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        //lr add 扫码交易
        Classification scanClassification = settleInfo.getScanClassification();
        mPrinter.appendPrnStr("扫码", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("扫码消费       " + scanClassification.getSaleNum(),
                StringUtils.formatAmount(String.valueOf(scanClassification.getSaleAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("扫码退货       " + scanClassification.getRefundNum(),
                StringUtils.formatAmount(String.valueOf(scanClassification.getRefundAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);

    }

    /**
     * 组织结算单打印数据
     *
     * @param settleInfo 结算信息
     * @param isRePrint  是否重打印
     */
    public static void formPrintSettleData(SettleInfo settleInfo, boolean isRePrint) {
        mPrinter.appendPrnStr("结算总计单", FONT_BIG, AlignEnum.CENTER);
        keeper(0, 1);
        mPrinter.appendPrnStr("商户名称:", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr(settleInfo.getMerchantName(), FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("商户编号:", settleInfo.getMerchantId(), FONT_NORMAL);
        mPrinter.appendPrnStr("终端编号:", settleInfo.getTerminalId(), FONT_NORMAL);
        mPrinter.appendPrnStr("操作员号:", String.format(SysConstant.LOCALE, "%02d", settleInfo.getOperator()), FONT_NORMAL);
        mPrinter.appendPrnStr("批次号:", settleInfo.getBatchNum(), FONT_NORMAL);
        mPrinter.appendPrnStr("结算时间:", StringUtils.formatDateTime(settleInfo.getDate(), settleInfo.getTime()), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        mPrinter.appendPrnStr("类型/TYPE   笔数/SUM", "金额/AMT", FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        if (settleInfo.getIsEqu()) {
            mPrinter.appendPrnStr("内卡对账平", FONT_NORMAL, AlignEnum.LEFT);
        } else {
            mPrinter.appendPrnStr("内卡对账不平", FONT_NORMAL, AlignEnum.LEFT);
        }
        Classification classification = settleInfo.getClassification();
        mPrinter.appendPrnStr("消费           " + classification.getSaleNum(),
                StringUtils.formatAmount(String.valueOf(classification.getSaleAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("电子现金消费   " + classification.getEcSaleNum(),
                StringUtils.formatAmount(String.valueOf(classification.getEcSaleAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("预授权完成     " + classification.getAuthCMNum(),
                StringUtils.formatAmount(String.valueOf(classification.getAuthCMAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
//        mPrinter.appendPrnStr("预授权完成通知 " + classification.getAuthCMNotifyNum(),
//                StringUtils.formatAmount(String.valueOf(classification.getAuthCMNotifyAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
//        mPrinter.appendPrnStr("预授权完成撤销 " + classification.getAuthCMVoidNum(),
//                StringUtils.formatAmount(String.valueOf(classification.getAuthCMVoidAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
//        mPrinter.appendPrnStr("撤销           " + classification.getVoidNum(),
//                StringUtils.formatAmount(String.valueOf(classification.getVoidAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("退货           " + classification.getRefundNum(),
                StringUtils.formatAmount(String.valueOf(classification.getRefundAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        if (settleInfo.getIsInterEqu()) {
            mPrinter.appendPrnStr("外卡对账平", FONT_NORMAL, AlignEnum.LEFT);
        } else {
            mPrinter.appendPrnStr("外卡对账不平", FONT_NORMAL, AlignEnum.LEFT);
        }
        Classification interClassification = settleInfo.getInterClassification();
        mPrinter.appendPrnStr("消费           " + interClassification.getSaleNum(),
                StringUtils.formatAmount(String.valueOf(interClassification.getSaleAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("电子现金消费   " + interClassification.getEcSaleNum(),
                StringUtils.formatAmount(String.valueOf(interClassification.getEcSaleAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("预授权完成     " + interClassification.getAuthCMNum(),
                StringUtils.formatAmount(String.valueOf(interClassification.getAuthCMAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
//        mPrinter.appendPrnStr("预授权完成通知 " + interClassification.getAuthCMNotifyNum(),
//                StringUtils.formatAmount(String.valueOf(interClassification.getAuthCMNotifyAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
//        mPrinter.appendPrnStr("预授权完成撤销 " + interClassification.getAuthCMVoidNum(),
//                StringUtils.formatAmount(String.valueOf(interClassification.getAuthCMVoidAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
//        mPrinter.appendPrnStr("撤销           " + interClassification.getVoidNum(),
//                StringUtils.formatAmount(String.valueOf(interClassification.getVoidAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("退货           " + interClassification.getRefundNum(),
                StringUtils.formatAmount(String.valueOf(interClassification.getRefundAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        //lr add 扫码交易
        Classification scanClassification = settleInfo.getScanClassification();
        mPrinter.appendPrnStr("扫码消费       " + scanClassification.getSaleNum(),
                StringUtils.formatAmount(String.valueOf(scanClassification.getSaleAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("扫码退货       " + scanClassification.getRefundNum(),
                StringUtils.formatAmount(String.valueOf(scanClassification.getRefundAmt()), SysConstant.FUND_DIGITS), FONT_NORMAL);
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
    }

    /**
     * 开始打印
     *
     * @param rollPaperEnd 打印结束是否切纸
     * @param listener     打印回调接口
     * @return
     */
    public static int startPrint(boolean rollPaperEnd, OnPrintListener listener) {
        return mPrinter.startPrint(rollPaperEnd, listener);
    }

    /**
     * 打印抬头
     */
    private static void formPrintTitle() {
        //判断打印单抬头打印类型
        Optional.ofNullable(mRepository.getParamValue(PreferencesConstants.PRINT_TITLE_SELECT))
                .filter(s -> !TextUtils.isEmpty(s) && "0".equals(s))
                .ifPresentOrElse(s -> {
//                    Bitmap bitmap = BitmapFactory.decodeResource(App.sContext.getResources(), R.drawable.cupprt);
                    Bitmap bitmap = BitmapFactory.decodeResource(App.sContext.getResources(), R.drawable.bccprt);
                    mPrinter.appendImage(bitmap, AlignEnum.CENTER);
                }, () -> mPrinter.appendPrnStr(Optional.ofNullable(mRepository.getParamValue(PreferencesConstants.PRINT_TITLE))
                        .filter(s -> !TextUtils.isEmpty(s))
                        .orElse(App.sContext.getString(R.string.default_print_title)), FONT_BIG, AlignEnum.CENTER));
    }

    /**
     * 存根
     *
     * @param printTimes 当前打印次数
     * @param totalTimes
     */
    private static void keeper(int printTimes, int totalTimes) {
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
        switch (printTimes) {
            case 0:
                mPrinter.appendPrnStr("商户存根", "MERCHANT COPY", FONT_NORMAL);
                break;
            case 1:
                if (totalTimes == 2) {
                    mPrinter.appendPrnStr("持卡人存根", "CARDHOLDER COPY", FONT_NORMAL);
                } else {
                    mPrinter.appendPrnStr("银行存根", "BANK COPY", FONT_NORMAL);
                }
                break;
            default:
                if (totalTimes == 3) {
                    mPrinter.appendPrnStr("持卡人存根", "CARDHOLDER COPY", FONT_NORMAL);
                } else {
                    mPrinter.appendPrnStr("银行存根", "BANK COPY", FONT_NORMAL);
                }
                break;
        }
        mPrinter.appendPrnStr("--------------------------------", FONT_NORMAL, AlignEnum.LEFT);
    }

    /**
     * 切纸
     */
    public static void cutPaper() {
        mPrinter.cutPaper();
    }

}
